/*
 * =====================================================================================
 *
 *       Filename:  ListenSocketLinux.h
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  2012-10-01
 *       Revision:  none
 *       Compiler:  cmake & gcc
 *
 *         Author:  ankjt
 *
 * =====================================================================================
 */

#ifndef __LISTENSOCKET_H__
#define __LISTENSOCKET_H__

#include "SocketDefines.h"
#include "SocketMgrLinux.h"
#include "SocketOps.h"
#include "Thread.h"

class ListenSocket : public Thread
{
public:
    ListenSocket()
    {
        m_pkMgr = NULL;
        FD_ZERO(&m_kListenFds);
    }
    ~ListenSocket()
    {
        for(int i = 0;i < m_kListenSockets.size();i++)
        {
            SocketOps::CloseSocket(m_kListenSockets[i]);
        }
    }

    void SetSocketMgr(SocketMgr* pkMgr)
    {
        m_pkMgr = pkMgr;
    }
    bool StartListen(const char * pkListenAddress,int iPort,int iSendBufferSize,int iRecvBufferSize)
    {
        m_iSendBufferSize = iSendBufferSize;
        m_iRecvBufferSize = iRecvBufferSize;
        SOCKET sSocket = socket(AF_INET, SOCK_STREAM, 0);
        SocketOps::ReuseAddr(sSocket);
        SocketOps::Nonblocking(sSocket);
        struct sockaddr_in kAddress;
        kAddress.sin_family = AF_INET;
        kAddress.sin_port = ntohs((u_short)iPort);
        kAddress.sin_addr.s_addr = htonl(INADDR_ANY);

        if(strcmp(pkListenAddress, "0.0.0.0"))
        {
            struct hostent * hostname = gethostbyname(pkListenAddress);
            if(hostname != 0)
            {
                memcpy(&kAddress.sin_addr.s_addr, hostname->h_addr_list[0], hostname->h_length);
            }
        }

        int ret = ::bind(sSocket, (const sockaddr*)&kAddress, sizeof(kAddress));
        if(ret != 0)
        {
            printf("Bind unsuccessful on port %u.\n", (unsigned int)iPort);
            return false;
        }

        ret = listen(sSocket, 5);
        if(ret != 0) 
        {
            printf("Unable to listen on port %u.\n", (unsigned int)iPort);
            return false;
        }
        printf("StartListen Thread Start port:[%d].\n",iPort);
        m_kListenSockets.push_back(sSocket);
        return true;
    }

    void Run()
    {
        printf("Listen Thread Run....................\n");
        while(Active())
        {
            FD_ZERO(&m_kListenFds);
            for(int i = 0;i < m_kListenSockets.size();i++)
            {
                FD_SET(m_kListenSockets[i],&m_kListenFds);
            }
            int iRet = select(FD_SETSIZE,&m_kListenFds,NULL,NULL,NULL);
            if(iRet != -1)
            {
                for(int i = 0;i < m_kListenSockets.size();i++)
                {
                    if(FD_ISSET(m_kListenSockets[i],&m_kListenFds))
                    {
                        OnAccept(m_kListenSockets[i]);
                        break;
                    }
                }
            }
        }
    }
    void OnAccept(SOCKET sFd)
    {
        printf("ListenSocket::OnAccept().\n");
        struct sockaddr_in kTempAddress;
        memset(&kTempAddress,0,sizeof(struct sockaddr_in));
        int iLen = sizeof(sockaddr_in);
        if(m_pkMgr->GetSocketCount() > 1000)
        {
            return;
        }
        SOCKET aSocket = accept(sFd,(sockaddr*)&kTempAddress,(socklen_t*)&iLen);
        if(aSocket <= 0)
        {
            printf("Create OnAccept fail.\n");
            return;
        }
        printf("Create OnAccept.[FD:%d]\n",aSocket);
        Socket* kSocket = m_pkMgr->CreateSocket(aSocket,m_iSendBufferSize,m_iRecvBufferSize);
        if(!kSocket)
        {
            printf("Create Socket Fail.\n");
            return;
        }

        //kSocket->SetServerAddr(m_kAddress);
        kSocket->Accept(&kTempAddress);
        m_pkMgr->GetCall()->OnAccept(aSocket,"192.168.0.1",1314);
        m_pkMgr->AddSocket(kSocket);
    }

private:
    SocketMgr*          m_pkMgr;
    std::vector<SOCKET> m_kListenSockets;
    fd_set              m_kListenFds;

    int                 m_iSendBufferSize;
    int                 m_iRecvBufferSize;
};


#endif

